﻿using System;
using System.Collections.Generic;
using System.Data;


namespace IncubatorServices
{
    public class Share
    {
        private int id;
        public User owner;
        public Company company;
        public bool isOnMarket;
        public int cost; //cost of each share (-1 if share is not on market)
        public int quantity; //number of shares
        public DateTime datePosted; //null if not on marketplace

        public Share()
        {
        }
        private Share(int id_, User o, Company c, bool onMarket, int cost_, int quantity_, DateTime datePosted_)
        {
            id = id_;
            owner = o;
            company = c;
            isOnMarket = onMarket;
            cost = cost_;
            quantity = quantity_;
            datePosted = datePosted_;
        }

        private void ParseShare(DataRow r)
        {
            id = sqlManager.GetDataInt(r["id"]);
            User u = new User();
            u.LoadData(sqlManager.GetDataInt(r["user_owner_id"]));
            owner = u;
            Company c = new Company();
            c.LoadData(sqlManager.GetDataInt(r["company_id"]));
            company = c;
            isOnMarket = (sqlManager.GetDataInt(r["onMarket"]) == 1);
            Int32.TryParse(sqlManager.GetData(r["cost"]), out cost);
            quantity = sqlManager.GetDataInt(r["quantity"]);
            //DateTime.TryParse(sqlManager.GetData(r["datePosted"]),out datePosted); ;
        }

        public void RegisterNewShares(Company c, User u, int q, bool onMarket, int cost_)
        { //create new shares for a newly created company
            owner = u;
            company = c;
            quantity = q;
            cost = cost_;
            datePosted = DateTime.MinValue;
            isOnMarket = onMarket;
            createNew();

        }

        //public bool GetShares(Company c, User u, bool onMarket)
        //{
        //    return GetShares(c, u, onMarket, -1);
        //}
        public bool GetShares(Company c, User u, bool onMarket, int cost)
        {   //sets the shares to the number of shares owned by u of company c
            //returns false if there are none, true otherwise   


            sqlManager sql = new sqlManager();
            string query = "SELECT id, user_owner_id, company_id, onMarket, quantity, cost, datePosted FROM shares WHERE user_owner_id = '" + u.id + "' AND company_id = '" + c.id + "' AND onMarket = '" + (onMarket ? 1 : 0) + "'";
            if (onMarket)
                query += " AND cost = '" + cost + "'";
            DataSet ds = sql.GetDataSet(query);
            if (ds.Tables[0].Rows.Count < 1) return false; //no shares
            if (ds.Tables[0].Rows.Count > 1) throw new Exception("Data Integrity Issue - Multiple share rows for 1 entry");
            ParseShare(ds.Tables[0].Rows[0]);

            return true;
        }
        public static List<Share> GetAllMarketShares()
        {
            sqlManager sql = new sqlManager();
            List<Share> result = new List<Share>();
            string query = "SELECT id, user_owner_id, company_id, onMarket, quantity, cost, datePosted FROM shares WHERE onMarket = '1'";
            DataSet ds = sql.GetDataSet(query);
            foreach (DataRow r in ds.Tables[0].Rows)
            {
                Share share = new Share();
                share.ParseShare(r);
                result.Add(share);
            }
            return result;
            //string query = "S
        }
        public static List<Share> GetAllUserShares(User u)
        {
            List<Share> result = new List<Share>();
            sqlManager sql = new sqlManager();
            string query = "SELECT id, user_owner_id, company_id, onMarket, quantity, cost, datePosted FROM shares WHERE user_owner_id = '" + u.id + "'";
            DataSet ds = sql.GetDataSet(query);
            foreach (DataRow r in ds.Tables[0].Rows)
            {
                Share share = new Share();
                share.ParseShare(r);
                result.Add(share);
            }

            return result;
        }
        public static List<Share> GetAllCompanyShares(Company c)
        {
            List<Share> result = new List<Share>();
            sqlManager sql = new sqlManager();
            string query = "SELECT id, user_owner_id, company_id, onMarket, quantity, cost, datePosted FROM shares WHERE company_id = '" + c.id + "'";
            DataSet ds = sql.GetDataSet(query);
            foreach (DataRow r in ds.Tables[0].Rows)
            {
                Share share = new Share();
                share.ParseShare(r);
                result.Add(share);
            }

            return result;
        }
        public static bool transferShares(Company c, User old_owner, User new_owner, int numShares, int cost)
        {//transfer num shares from current user to user destination
            //returns result of transaction
            Share newShares = new Share();
            Share oldShares = new Share();

            if (!oldShares.GetShares(c, old_owner, true, cost))
            {
                throw new Exception("owner does not own any shares of this company on market");
            }
            if (oldShares.quantity < numShares)
                throw new Exception("owner does not have this many shares up on the market");
            //remove old shares
            oldShares.quantity = oldShares.quantity - numShares;
            oldShares.storeData();
            if (oldShares.quantity <= 0) //all shares have been sold
                oldShares.delete();

            if (!newShares.GetShares(c, new_owner, false, cost))
            {
                //user has no shares out of market
                //create new shares row with the shares just bought
                newShares.RegisterNewShares(c, new_owner, numShares, false, -1);
            }
            else
            {
                //add shares amount to current row
                newShares.quantity = newShares.quantity + numShares;
                newShares.storeData();
            }
            newShares.cost = -1;
            newShares.storeData();
            return true;
        }
        public static void PutOnMarket(Company c, User owner, int numShares, int cost_per_share)
        {
            //transfer num shares to market
            //returns result of transaction
            Share newShares = new Share();
            Share oldShares = new Share();

            if (!oldShares.GetShares(c, owner, false, cost_per_share))
            {
                throw new Exception("owner does not own any shares of this company out of market");
            }
            if (oldShares.quantity < numShares)
                throw new Exception("owner does not have this many shares out of market");
            //remove old shares
            oldShares.quantity = oldShares.quantity - numShares;
            oldShares.storeData();
            if (oldShares.quantity <= 0) //all shares have been sold
                oldShares.delete();

            if (!newShares.GetShares(c, owner, true, cost_per_share))
            {
                //user has no shares on market with the same cost 
                //create new shares row with the shares just sold
                newShares.RegisterNewShares(c, owner, numShares, true, cost_per_share);
            }
            else
            {
                //add shares amount to current row
                newShares.quantity = newShares.quantity + numShares;
                newShares.storeData();

            }
            newShares.cost = cost_per_share;
            newShares.storeData();
        }
        private void storeData()
        {
            sqlManager sql = new sqlManager();
            string query = "UPDATE shares SET user_owner_id = '" + owner.id + "', company_id = '" + company.id + "', onMarket = '" + (isOnMarket ? 1 : 0) + "', quantity = '" + quantity + "', cost = '" + cost + "' WHERE id = '" + id + "'";
            sql.NonQuery(query);
        }
        private void delete()
        {
            sqlManager sql = new sqlManager();
            string query = "DELETE FROM shares WHERE id = '" + id + "'";
            sql.NonQuery(query);
        }
        private int createNew()
        {
            sqlManager sql = new sqlManager();
            string query = "INSERT INTO shares (user_owner_id, company_id, onMarket, quantity, cost) VALUES('" + owner.id + "','" + company.id + "','" + (isOnMarket ? 1 : 0) + "','" + quantity + "','" + cost + "')";
            sql.NonQuery(query);
            return Int32.Parse(sql.GetScalar("SELECT MAX(id) as max FROM shares"));

        }
        public static void splitProfits(Company c, int profits)
        {//split profits among shareholders of the company
            List<Share> shares = GetAllCompanyShares(c);
            foreach (Share s in shares)
            {
                Company owner = new Company();
                owner.LoadData(s.owner.company_id);
                owner.money += (int)Math.Round(((1.0 * s.quantity) / 100.0) * profits);
                owner.storeData();
            }
        }

    }
}